#include <stdlib.h>

#include "maps.h"

float maps::get_lat(int coorY) 
{
	return 90 - ((180/config.maxVerticalImagesCount)*(coorY+1));
}

float maps::get_lon(int coorX)
{
	return -180 + ( (360/config.maxHorizontalImagesCount)*coorX );
}

float maps::get_dif_lat() {

	return (180/config.maxVerticalImagesCount);
}

float maps::get_dif_lon() {

	return (360/config.maxHorizontalImagesCount);
}

int maps::get_coorY(float lat)
{

	return ( ((float)config.maxVerticalImagesCount/180)*(90-lat) - 1 );
}

int maps::get_coorX(float lon) 
{

	return ( ( lon + 180 )*( (float)config.maxHorizontalImagesCount/360 ) );
}

int maps::get_max_X(int zoom) {

	switch ( zoom ){
      case 10:
		return 20;
        break;
	  case 9:
		return 20;
        break;
	  case 8:
		return 20;
        break;
	  case 7:
		return 20;
        break;
	  case 6:
		return 20;
        break;
	  case 5:
		return 10;
        break;
	  case 4:
		return 10;
        break;
	  case 3:
		return 10;
        break;
	  case 2:
		return 8;
        break;
	  case 1:
		return 4;
        break;
	  default: 
		  return 20;
    }
}

int maps::get_max_Y(int zoom) {

	switch ( zoom ){
      case 10:
		return 10;
        break;
	  case 9:
		return 10;
        break;
	  case 8:
		return 10;
        break;
	  case 7:
		return 10;
        break;
	  case 6:
		return 10;
        break;
	  case 5:
		return 5;
        break;
	  case 4:
		return 5;
        break;
	  case 3:
		return 5;
        break;
	  case 2:
		return 4;
        break;
	  case 1:
		return 2;
        break;
	  default: 
		  return 10;
    }
}

int maps::get_image_height(int zoom) {

	switch ( zoom ){
	  case 10:
		return 270;
        break;
	  case 9:
		return 245;
        break;
	  case 8:
		return 220;
        break;
	  case 7:
		return 195;
        break;
	  case 6:
		return 170;
        break;
	  case 5:
		return 290;
        break;
	  case 4:
		return 240;
        break;
	  case 3:
		return 190;
        break;
	  case 2:
		return 175;
        break;
	  case 1:
		return 225;
        break;
	  default: 
		  return 270;
      
    }

}
int maps::get_image_width(int zoom) {
	
	switch ( zoom ){
      case 10:
		return 270;
        break;
	  case 9:
		return 245;
        break;
	  case 8:
		return 220;
        break;
	  case 7:
		return 195;
        break;
	  case 6:
		return 170;
        break;
	  case 5:
		return 290;
        break;
	  case 4:
		return 240;
        break;
	  case 3:
		return 190;
        break;
	  case 2:
		return 175;
        break;
	  case 1:
		return 225;
        break;
	  default: 
		  return 270;
    }

}

int maps::get_zoom() {

	switch ( config.actualZoom ){
      case 10:
		return 10;
        break;
	  case 9:
		return 10;
        break;
	  case 8:
		return 8;
        break;
	  case 7:
		return 8;
        break;
	  case 6:
		return 8;
        break;
	  case 5:
		return 5;
        break;
	  case 4:
		return 4;
        break;
	  case 3:
		return 3;
        break;
	  case 2:
		return 2;
        break;
	  case 1:
		return 1;
        break;
	  default: 
		  return 10;
    }
}

maps::maps() 
{
	config.minZoom=1;
	config.maxZoom=10;
	config.actualZoom=1;
	config.imageHeight=get_image_height(config.actualZoom);
	config.imageWidth=get_image_width(config.actualZoom);
	config.maxHorizontalImagesCount=get_max_X(config.actualZoom);
	config.maxVerticalImagesCount=get_max_Y(config.actualZoom);
}


maps::~maps() 
{
}

net_fnc_s opcd maps::accept_connect(int start_lat, int start_lon, int start_zoom, net_out cConfiguration & configuration)
{	
	config.startImage.zoom=start_zoom;
	config.actualZoom=start_zoom;
	config.imageHeight=get_image_height(config.actualZoom);
	config.imageWidth=get_image_width(config.actualZoom);
	config.maxHorizontalImagesCount=get_max_X(config.actualZoom);
	config.maxVerticalImagesCount=get_max_Y(config.actualZoom);
	//		only testing values
	config.startImage.coorX=get_coorX(start_lon);
	config.startImage.coorY=get_coorY(start_lat);
	config.startImage.minLat=get_lat(config.startImage.coorY);
	config.startImage.minLon=get_lon(config.startImage.coorX);
	config.startImage.maxLat=config.startImage.minLat+get_dif_lat();
	config.startImage.maxLon=config.startImage.minLon+get_dif_lon();

	//
	char buffer[50];
	if ( ( config.startImage.coorY >= 0 ) && (config.startImage.coorX >= 0 ) && (config.startImage.coorX < config.maxHorizontalImagesCount) && (config.startImage.coorY < config.maxVerticalImagesCount) ) {
		sprintf(buffer, "images/map/zoom%02d/map-%02d-%02d.jpg", config.actualZoom, config.startImage.coorX, config.startImage.coorY );
	} else {
		sprintf(buffer, "null");
	}
	config.startImage.location.assign(buffer);
	configuration=config;
	return 0;
}

net_fnc opcd maps::change_zoom( net_in cImagePosition & imagePosition, net_out cConfiguration & configuration) {

	config.startImage.zoom=imagePosition.zoom;
	config.actualZoom=imagePosition.zoom;
	config.imageHeight=get_image_height(config.actualZoom);
	config.imageWidth=get_image_width(config.actualZoom);
	config.maxHorizontalImagesCount=get_max_X(config.actualZoom);
	config.maxVerticalImagesCount=get_max_Y(config.actualZoom);
	//		only testing values
	config.startImage.coorX=get_coorX(imagePosition.longitude);
	config.startImage.coorY=get_coorY(imagePosition.latitude);
	config.startImage.minLat=get_lat(config.startImage.coorY);
	config.startImage.minLon=get_lon(config.startImage.coorX);
	config.startImage.maxLat=config.startImage.minLat+get_dif_lat();
	config.startImage.maxLon=config.startImage.minLon+get_dif_lon();
	//
	char buffer[50];
	if ( ( config.startImage.coorY >= 0 ) && (config.startImage.coorX >= 0 ) && (config.startImage.coorX < config.maxHorizontalImagesCount) && (config.startImage.coorY < config.maxVerticalImagesCount) ) {
		sprintf(buffer, "images/map/zoom%02d/map-%02d-%02d.jpg", get_zoom(), config.startImage.coorX, config.startImage.coorY );
	} else {
		sprintf(buffer, "null");
	}
	config.startImage.location.assign(buffer);
	configuration=config;
	return 0;
}

net_fnc opcd maps::get_image_by_XY(net_in cImagePosition & imagePosition, net_out cMapImage & imageOut)
{
	char buffer[50];
	if ( ( imagePosition.cY >= 0 ) && (imagePosition.cX >= 0 ) && (imagePosition.cX < config.maxHorizontalImagesCount) && (imagePosition.cY < config.maxVerticalImagesCount) ) {
		sprintf(buffer, "images/map/zoom%02d/map-%02d-%02d.jpg", get_zoom(), imagePosition.cX, imagePosition.cY );
	} else {
		sprintf(buffer, "null");
	}
	imageOut.location.assign(buffer);
	imageOut.coorX=imagePosition.cX;
	imageOut.coorY=imagePosition.cY;
	imageOut.minLat=get_lat(imageOut.coorY);
	imageOut.minLon=get_lon(imageOut.coorX);
	imageOut.maxLat=imageOut.minLat+get_dif_lat();
	imageOut.maxLon=imageOut.minLon+get_dif_lon();
	imageOut.zoom=imagePosition.zoom;

	return 0;
}

net_fnc opcd maps::get_image_by_lon_lat(net_in cImagePosition & imagePosition, net_out cMapImage & imageOut)
{
	char buffer[50];
	if ( ( imagePosition.cY >= 0 ) && (imagePosition.cX >= 0 ) && (imagePosition.cX < config.maxHorizontalImagesCount) && (imagePosition.cY < config.maxVerticalImagesCount) ) {
		sprintf(buffer, "images/map/zoom%02d/map-%02d-%02d.jpg", get_zoom(), imagePosition.cX, imagePosition.cY );
	} else {
		sprintf(buffer, "null");
	}
	imageOut.location.assign(buffer);
	imageOut.coorX=get_coorX(imagePosition.longitude);
	imageOut.coorY=get_coorY(imagePosition.latitude);
	imageOut.minLat=get_lat(imageOut.coorY);
	imageOut.minLon=get_lon(imageOut.coorX);
	imageOut.maxLat=imageOut.minLat+get_dif_lat();
	imageOut.maxLon=imageOut.minLon+get_dif_lon();
	imageOut.zoom=imagePosition.zoom;

	return 0;
}